package com.ruoyi.auth.integration.authenticator.sms;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.auth.api.model.dto.UserLoginInfoDto;
import com.ruoyi.auth.integration.IntegrationAuthentication;
import com.ruoyi.auth.integration.authenticator.AbstractPreparableIntegrationAuthenticator;
import com.ruoyi.auth.integration.authenticator.sms.event.SmsAuthenticateBeforeEvent;
import com.ruoyi.auth.integration.authenticator.sms.event.SmsAuthenticateSuccessEvent;
import com.ruoyi.auth.service.UserLoginInfoServiceImpl;
import com.ruoyi.auth.verification.service.VerificationCodeService;
import com.ruoyi.common.core.exception.BaseException;
import com.ruoyi.common.core.web.component.LocaleMessageSourceHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * 短信验证码集成认证
 *
 * @author LIQIU
 * @date 2018-3-31
 **/
@Component
public class SmsIntegrationAuthenticator extends AbstractPreparableIntegrationAuthenticator implements ApplicationEventPublisherAware {

    @Autowired
    public UserLoginInfoServiceImpl userLoginInfoServiceImpl;

    @Autowired
    private PasswordEncoder passwordEncoder;

    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private VerificationCodeService verificationCodeService;

    private final static String SMS_AUTH_TYPE = "sms";

    @Autowired
    private LocaleMessageSourceHandler sourceHandler;

    @Override
    public UserLoginInfoDto authenticate(IntegrationAuthentication integrationAuthentication) {

        //获取授权类别
        String userCategory = integrationAuthentication.getUserCategory();
        //获取密码，实际值是验证码
        String password = integrationAuthentication.getAuthParameter("password");
        //邀请码
        String inviteCode = integrationAuthentication.getAuthParameter("invite_code");
        //电话
        String phone = integrationAuthentication.getAuthParameter("phone");
        if (StrUtil.isEmpty(phone)) {
            throw new BaseException("手机号码不能为空");
        }
        if (!ReUtil.contains("^[1][0-9][0-9]\\d{8}$", phone)) {
            throw new BaseException("手机号码不合法");
        }
        //获取用户名，实际值是手机号
        //String username = integrationAuthentication.getUsername();
        //发布事件，可以监听事件进行自动注册用户
        this.applicationEventPublisher.publishEvent(new SmsAuthenticateBeforeEvent(integrationAuthentication));
        //通过手机号码查询用户
        UserLoginInfoDto userLoginInfoDto = userLoginInfoServiceImpl.getUserApiService(userCategory).getUserInfoByPhone(phone, inviteCode);
//        UserLoginInfoDto userLoginInfoDto = null;
        //UserLoginInfoDto sysUserAuthentication = userLoginInfoServiceImpl.getUserApiService(userCategory).findUserByPhoneNumber(username);
        if (userLoginInfoDto != null) {
            if (password == null) {
                userLoginInfoDto.setPassword(null);
            } else {
                userLoginInfoDto.setPassword(passwordEncoder.encode(password));
            }
            //发布事件，可以监听事件进行消息通知
            this.applicationEventPublisher.publishEvent(new SmsAuthenticateSuccessEvent(integrationAuthentication));
        }
        return userLoginInfoDto;
    }

    @Override
    public void prepare(IntegrationAuthentication integrationAuthentication) {
        String code = integrationAuthentication.getAuthParameter("code");
        String codeToken = integrationAuthentication.getAuthParameter("code_token");
        String phone = integrationAuthentication.getAuthParameter("phone");
        boolean result = verificationCodeService.validate(codeToken, code, phone);
        if (!result) {
            throw new BaseException(sourceHandler.getMessage("VERIFICATION_CODE_EXCEPTION")).setCode("400").setStatus(400);
        }
    }

    @Override
    public boolean support(IntegrationAuthentication integrationAuthentication) {
        return SMS_AUTH_TYPE.equals(integrationAuthentication.getAuthType());
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }
}
